/*
 * ???????? 2006-1-12
 *
 * ?????????
 * 
 */
package com.szgd.util;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Calendar;

/**
 * @author Administrator
 */
public class TimeUtil {
    static final SimpleDateFormat DATE_FORMATE = new SimpleDateFormat("yyyy-MM-dd");
    static final SimpleDateFormat TIME_FORMATE = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    static Calendar G_CALENDAR = new java.util.GregorianCalendar();

    /**
     * @return 当前时间
     */
    public static Date getCurrentTime() {
        return new Date();
    }

    public static String format(Date date, String formatStr) {
        SimpleDateFormat newFormat = new SimpleDateFormat(formatStr);
        return newFormat.format(date);
    }

    /**
     * 获得当前时间 年月日时分秒
     * @return yyyy-MM-dd hh:mm:ss字符串
     */
    public static String getCurrentTimeStr() {
        return formatTime(getCurrentTime());
    }

    /**
     * 获得当前日期
     * @return yyyy-MM-dd 字符串
     */
    public static String getCurrentDateStr() {
        return formatDate(getCurrentTime());
    }

    /**
     * 获得当前年份
     * @return
     */
    public static int getCurrentYear() {
        return Calendar.getInstance().get(Calendar.YEAR);
    }

    /**
     * ????????
     *
     * @param date
     * @return String
     */
    public static String formatTime(Date date) {
        if (null == date) {
            return null;
        }

        return TIME_FORMATE.format(date);
    }

    /**
     * ????????
     *
     * @param timeStr
     * @return String
     */
    public static String formatTime(String timeStr) {
        if (null == timeStr) {
            return null;
        }

        Date date = parseTime(timeStr);

        return formatTime(date);
    }

    /**
     * ?????????
     *
     * @param dateStr
     * @return String
     */
    public static String formatDate(String dateStr) {
        if (null == dateStr) {
            return null;
        }

        Date date = parseDate(dateStr);

        return formatDate(date);
    }

    /**
     * ?????????
     *
     * @param date
     * @return String
     */
    public static String formatDate(Date date) {
        if (null == date) {
            return null;
        }

        return DATE_FORMATE.format(date);
    }

    /**
     * ???????????????????
     *
     * @param date    ???
     * @param pattern ???
     * @return
     */
    public static String formatDate(Date date, String pattern) {
        if (null == date || pattern == null) {
            return null;
        }

        return new SimpleDateFormat(pattern).format(date);
    }

    /**
     * 解析字符串日期
     *
     * @param dateStr yyyy-MM-dd
     * @return Date 国际化标准的Date对象
     */
    public static Date parseDate(String dateStr) {
        if (null == dateStr) {
            return null;
        }

        Date date = null;
        try {
            date = DATE_FORMATE.parse(dateStr);
        } catch (ParseException e) {
        }

        return date;
    }

    public static Date parseDate(String dateStr, String pattern) {
        if (pattern != null) {
            try {
                return new SimpleDateFormat(pattern).parse(dateStr);
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 解析时间
     *
     * @param timeStr yyyy-MM-dd hh:mm:ss
     * @return Date 国际化标准格式的Date对象
     */
    public static Date parseTime(String timeStr) {
        if (null == timeStr) {
            return null;
        }

        Date date = null;
        try {
            date = TIME_FORMATE.parse(timeStr);
        } catch (ParseException e) {
        }

        return date;
    }

    /**
     * ??????????????(???????????
     *
     * @param skipDay ???????
     * @return Date ???????
     */
    public static Date getSkipTime(int skipDay) {
        return getSkipTime(getCurrentTime(), skipDay);
    }

    /**
     * ?????????????(???????????
     *
     * @param date
     * @param skipDay ???????
     * @return Date ???????
     */
    public static Date getSkipTime(Date date, int skipDay) {
        G_CALENDAR.setTime(date);
        G_CALENDAR.add(Calendar.DAY_OF_MONTH, skipDay);

        return G_CALENDAR.getTime();
    }

    /**
     * ??????????????(?????????????��????????
     *
     * @param skipDay    ???????
     * @param skipHour   ????
     * @param skipMinute ????
     * @return Date ???????
     */
    public static Date getSkipTime(int skipDay, int skipHour, int skipMinute) {
        return getSkipTime(getCurrentTime(), skipDay, skipHour, skipMinute);
    }

    /**
     * ?????????????(?????????????��????????
     *
     * @param date       ????
     * @param skipDay    ???????
     * @param skipHour   ????
     * @param skipMinute ????
     * @return Date ??????
     */
    public static Date getSkipTime(Date date, int skipDay, int skipHour, int skipMinute) {
        if (null == date) {
            return null;
        }
/*		
        G_CALENDAR.setTime(date);
		G_CALENDAR.add(Calendar.DAY_OF_MONTH, skipDay);
		G_CALENDAR.add(Calendar.HOUR_OF_DAY, skipHour);	
		G_CALENDAR.add(Calendar.MINUTE, skipMinute);
		G_CALENDAR.get(Calendar.DAY_OF_WEEK_IN_MONTH);
		
		return G_CALENDAR.getTime();	
        
*/
        return getSkipTime(date, 0, 0, skipDay, skipHour, skipMinute);
    }

    /**
     * ?????????????
     *
     * @param date       ????
     * @param skipYear   ???????
     * @param skipMonth  ???????
     * @param skipDay    ???????
     * @param skipHour   ��??????
     * @param skipMinute ???????
     * @return ??????
     */
    public static Date getSkipTime(Date date, int skipYear, int skipMonth, int skipDay, int skipHour, int skipMinute) {
        if (null == date) {
            return null;
        }

        G_CALENDAR.setTime(date);
        G_CALENDAR.add(Calendar.YEAR, skipYear);
        G_CALENDAR.add(Calendar.MONTH, skipMonth);
        G_CALENDAR.add(Calendar.DAY_OF_MONTH, skipDay);
        G_CALENDAR.add(Calendar.HOUR_OF_DAY, skipHour);
        G_CALENDAR.add(Calendar.MINUTE, skipMinute);

        return G_CALENDAR.getTime();
    }

    private static final int MSEL_OF_MIN = 1000 * 60;
    private static final int MSEL_OF_HOUR = 1000 * 3600;
    private static final int MSEL_OF_DAY = MSEL_OF_HOUR * 24;

    /**
     * ???????????��???
     *
     * @param base    ???????
     * @param compare ????
     * @return long ????
     */
    public static long getSubhour(Date base, Date compare) {//subtrahend

        long daterange = base.getTime() - compare.getTime();
        long time = MSEL_OF_HOUR;

        return (daterange % time == 0) ? (daterange / time) : (daterange / time + 1);
    }

    /**
     * ????????????????
     *
     * @param base
     * @param compare
     * @return
     */
    public static long getSubMin(Date base, Date compare) {//subtrahend

        long daterange = base.getTime() - compare.getTime();
        long time = MSEL_OF_MIN;

        return (daterange % time == 0) ? (daterange / time) : (daterange / time + 1);
    }


    /**
     * ?????????????
     *
     * @param base    ???????
     * @param compare ????
     * @return long ?????
     */
    public static long getSubday(Date base, Date compare) {//subtrahend

        long daterange = base.getTime() - compare.getTime();
        long time = MSEL_OF_DAY;

        return (daterange % time == 0) ? (daterange / time) : (daterange / time + 1);
    }

    /**
     * @param date
     * @return ????????
     */
    public static int dayOfWeek(Date date) {
        return getFieldOfDate(date, Calendar.DAY_OF_WEEK);
    }

    /**
     * ????????????????????��???? com.util.Calendar??
     *
     * @param date  ???????
     * @param field @see com.util.Calendar
     * @return
     */
    public static int getFieldOfDate(Date date, int field) {
        G_CALENDAR.setTime(date);
        return G_CALENDAR.get(field);
    }

    static void test1() {

        System.out.println("path: " + File.separator);
        System.out.println("????????" + getCurrentDateStr());
        System.out.println("??????" + getCurrentTimeStr());

        Date date = parseTime("2003-08-8 8:08:08");
        System.out.println("????2003-08-8 8:08:08 ：：" + date.toString());

        Date date2 = parseDate("2003-08-8");
        System.out.println("????2003-08-8   ：：" + date2.toString());

        System.out.println("????? ：：" + formatDate(getSkipTime(2)));
        System.out.println("???????? ：：" + formatDate(getSkipTime(-14)));

        System.out.println("???????? ：：" + formatTime(getSkipTime(0, 0, -1)));
        System.out.println("?????? ：：" + formatTime(getSkipTime(0, 0, 1)));

        System.out.println("??????��????????? ：：" + formatTime(getSkipTime(-1, -1, -1)));

        Date cTime = parseTime(getCurrentTimeStr());
        Date bTime = getSkipTime(0, 0, -1);
        Date lTime = getSkipTime(0, 0, 1);

        System.out.println(cTime.compareTo(bTime));
        System.out.println(cTime.compareTo(lTime));
        System.out.println(cTime.compareTo(cTime));

        Date btime = TimeUtil.getSkipTime(0, 0, -15);
        Date ltime = TimeUtil.parseTime("2004-3-24 8:10:30");

        if (btime.compareTo(ltime) > 0) {
            System.out.println("???????15??");
        } else {
            System.out.println("???��??15??");
        }

        System.out.println("?????2001-04-09 14:39:00.000   ：：" + formatTime("2001-04-09 14:39:00.000"));
        System.out.println("?????2001-04-09 14:2:3.000  ：：" + formatTime("2001-04-09 14:2:3.000"));
        System.out.println("?????2004-04-01 00:00:00.000  ：： " + formatDate("2004-04-01 00:00:00.000"));
        System.out.println("?????2004-04-01 10:03:00.000   ：：" + formatDate("2004-04-01 10:03:00.000"));

        System.out.print("2004-04-01-> 2004-04-02 ??????? ：：");
        System.out.println(getSubday(parseDate("2004-04-01"), parseDate("2004-04-02")));
        System.out.print("2004-6-1 22:22:00-> 2004-5-31 22:22:00 ??????? ：：");
        System.out.println(getSubday(parseTime("2004-6-1 22:22:00"), parseTime("2004-5-31 22:22:00")));
        System.out.print("2004-6-1 23:22:00-> 2004-5-31 22:22:00 ???????");
        System.out.println(getSubday(parseTime("2004-6-1 23:22:00"), parseTime("2004-5-31 22:22:00")));
        System.out.print("2004-4-1 ?????:");
        System.out.println(formatDate(getSkipTime(parseDate("2004-4-1"), 1)));
        System.out.print("2004-04-01 ?????");
        System.out.println(formatDate(getSkipTime(parseDate("2004-4-1"), -2)));
        System.out.print("2004-4-1 10:10:10 ?????");
        System.out.println(formatDate(getSkipTime(parseTime("2004-4-1 10:10:10"), -2)));

        System.out.print("2004-2-22 22:22:00-> 2004-2-20 21:22:00 ???��???");
        System.out.println(getSubhour(parseTime("2004-2-22 22:22:00"), parseTime("2004-2-21 21:22:00")));
        System.out.print("2004-3-1 22:22:00-> 2004-2-27 22:22:00 ???��???");
        System.out.println(getSubhour(parseTime("2004-3-1 22:22:00"), parseTime("2004-2-27 22:22:00")));
        System.out.print("2005-3-1 22:22:00-> 2005-2-27 22:22:00 ???��???");
        System.out.println(getSubhour(parseTime("2005-3-1 22:22:00"), parseTime("2005-2-27 22:22:00")));
        System.out.print("2004-4-1 23:22:00-> 2004-3-31 22:22:00 ???��???");
        System.out.println(getSubhour(parseTime("2004-4-1 22:22:00"), parseTime("2004-3-31 23:22:00")));
    }

    static void test2() {
        Date date = TimeUtil.getCurrentTime();
        Date date2 = TimeUtil.getSkipTime(date, 2, 13, 5, 4, 30);
        System.out.println(TimeUtil.formatTime(date));
        System.out.println(TimeUtil.formatTime(date2));

        ;
    }

    /**
     * @param date ??????null
     * @return ????????????? ????????? + ???? eg??2008??9??8?? ?????
     */
    public static String getDateDayCN(Date date) {
        if (date == null) {
            date = new Date();
        }
        G_CALENDAR.setTime(date);
        int y = G_CALENDAR.get(G_CALENDAR.YEAR);
        int m = G_CALENDAR.get(G_CALENDAR.MONTH) + 1;
        int d = G_CALENDAR.get(G_CALENDAR.DAY_OF_MONTH);
        int w = G_CALENDAR.get(G_CALENDAR.DAY_OF_WEEK) - 1;
        String[] dayCN = {"??", "?", "??", "??", "??", "??", "??",};
        return y + "??" + m + "??" + d + "?? ????" + dayCN[w];
    }

    public static String getWelcomeStr(Date date) {
        if (date == null) {
            date = new Date();
        }
        G_CALENDAR.setTime(date);
        int h = G_CALENDAR.get(G_CALENDAR.HOUR_OF_DAY);
        String str = "????";
        if (h < 6) {
            str = "?ْ";
        } else if (h < 8) {
            str = "????";
        } else if (h < 12) {
            str = "????";
        } else if (h < 14) {
            str = "????";
        } else if (h < 18) {
            str = "????";
        }

        return str + "??";
    }

    public static void main(String[] args) {
        Long millisecond = Instant.now().toEpochMilli();  // 精确到毫秒
        Long second = Instant.now().getEpochSecond();  // 精确到毫秒

        System.out.println("millisecond:"+millisecond);
        System.out.println("second:"+second);
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        System.out.println("millisecond:"+ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(millisecond), ZoneId.systemDefault())));
        System.out.println("second:"+ftf.format(LocalDateTime.ofInstant(Instant.ofEpochSecond(millisecond/ 1000l +1), ZoneId.systemDefault())));

        long now = System.currentTimeMillis() / 1000l;
        long daySecond = 60 * 60 * 24;
        long dayTime = now - (now + 8 * 3600) % daySecond;
        System.out.println("www.jb51.net - 今天凌晨时间戳"+dayTime);

        //test1();
        // test2();
    }

    public static String getMonthStartDate(Date date) {
        if (date == null)
            date = new Date();
        String day = "01";
        G_CALENDAR.setTime(date);
        int year = G_CALENDAR.get(G_CALENDAR.YEAR);
        int m = G_CALENDAR.get(G_CALENDAR.MONTH) + 1;

        String mstr = m + "-";
        if (m < 10) {
            mstr = "0" + mstr;
        }
        return year + "-" + mstr + day;

    }

    public static String getMonthLastDate(Date date) {
        if (date == null)
            date = new Date();
        String day = "31";
        G_CALENDAR.setTime(date);
        int year = G_CALENDAR.get(G_CALENDAR.YEAR);
        int m = G_CALENDAR.get(G_CALENDAR.MONTH) + 1;
        if (m == 4 || m == 6 || m == 9 || m == 11) {
            day = "30";
        }
        if (m == 2) {
            if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))) {
                day = "29";
            } else {
                day = "28";
            }
        }
        String mstr = m + "-";
        if (m < 10) {
            mstr = "0" + mstr;
        }
        return year + "-" + mstr + day;

    }

    public static int getMonth(Date date) {
        if (date == null)
            date = new Date();
        G_CALENDAR.setTime(date);
        return G_CALENDAR.get(G_CALENDAR.MONTH) + 1;
    }

    public static String getMonthStr(Date date) {
        if (date == null)
            date = new Date();
        G_CALENDAR.setTime(date);
        int month = G_CALENDAR.get(G_CALENDAR.MONTH) + 1;
        String tempStr = "0" + month;
        return tempStr.substring(tempStr.length() - 2, tempStr.length());
    }

    public static int getYear(Date date) {
        if (date == null)
            date = new Date();
        G_CALENDAR.setTime(date);
        return G_CALENDAR.get(G_CALENDAR.YEAR);
    }

    /**
     * @param timeStr
     * @param length  ????????
     * @return ???????????
     */
    public static String getDateTime(String timeStr, int length) {
        if (timeStr != null) {
            return timeStr.substring(11, 11 + length);
        }
        return "";
    }

    public static int getWeekOfYear(Date date) {
        if (date == null)
            date = new Date();
        G_CALENDAR.setTime(date);
        return G_CALENDAR.get(G_CALENDAR.WEEK_OF_YEAR);
    }

    /**
     * @param date
     * @return ???Date.getDay()
     */
    public static int getDayOfWeek(Date date) {
        if (date == null)
            date = new Date();
        G_CALENDAR.setTime(date);
        return G_CALENDAR.get(G_CALENDAR.DAY_OF_WEEK);
    }

    /**
     * @param date
     * @return ???Date.getHours()
     */
    public static int getHours(Date date) {
        if (date == null)
            date = new Date();
        G_CALENDAR.setTime(date);
        return G_CALENDAR.get(G_CALENDAR.HOUR_OF_DAY);
    }

    /**
     * @param date
     * @return ???Date.getMinutes()
     */
    public static int getMinutes(Date date) {
        if (date == null)
            date = new Date();
        G_CALENDAR.setTime(date);
        return G_CALENDAR.get(G_CALENDAR.MINUTE);
    }

    public static Date getFirstOfWeek(int year, int weekOfYear) {
        return getFirstOfWeek(year, weekOfYear, false);
    }

    public static Date getFirstOfWeek(int year, int weekOfYear, boolean is0101) {
        Date firstDay = TimeUtil.parseDate(year + "-01-01");
        if (weekOfYear == 1 && is0101) {
            return firstDay;
        } else {
            int firstDayOfWeek = getDayOfWeek(firstDay);
            firstDay = TimeUtil.getSkipTime(firstDay, (weekOfYear - 1) * 7 - firstDayOfWeek + 2);
        }
        return firstDay;
    }

    public static Date addDays(Date date, int days) {
        G_CALENDAR.setTime(date);
        G_CALENDAR.add(Calendar.DAY_OF_YEAR, days);
        return G_CALENDAR.getTime();
    }

    public static Date addDays(String dateStr, int days) {
        return addDays(parseDate(dateStr), days);

    }

    public static Date getFirstDayOfYear() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, 1);
        return calendar.getTime();
    }

    /*************判断日期是否有效***************/
    public static boolean isValidDate(String str) {
        boolean convertSuccess=true;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            format.setLenient(false);
            format.parse(str);
        } catch (ParseException e) {
            convertSuccess=false;
        }
        return convertSuccess;
    }

    /*************判断日期是否有效yyyy-MM-dd HH:mm***************/
    public static boolean isValidDateToMin(String str) {
        boolean convertSuccess=true;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        try {
            format.setLenient(false);
            format.parse(str);
        } catch (ParseException e) {
            convertSuccess=false;
        }
        return convertSuccess;
    }

    /*************根据开始日期与结束日期计算时长***************/
    public static String transferTime(String start,String end,String type){
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (end == null || end.length() ==0) {
            end = sd.format(new Date());
        }
        if (start.length()  > 0 && start.length() > 0) {
            long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
            long nh = 1000 * 60 * 60;// 一小时的毫秒数
            long nm = 1000 * 60;// 一分钟的毫秒数

            long lEnterTime = 0;
            long lExitTime = 0;
            try {
                lEnterTime = sd.parse(start).getTime();
                lExitTime = sd.parse(end).getTime();
            } catch (ParseException e) {
                e.printStackTrace();
            }
            long diff = lExitTime - lEnterTime;
            long day = diff / nd;// 计算差多少天
            long hour = diff % nd / nh + day * 24;// 计算差多少小时
            long min = diff % nd % nh / nm + day * 24 * 60;// 计算差多少分钟
            String stayHours;
            if (type.equalsIgnoreCase("hour")) {
                stayHours =  day + "天" + (hour - day * 24) + "小时";
            }else{
                stayHours =  day + "天" + (hour - day * 24) + "小时"
                        + (min - day * 24 * 60) + "分钟" ;
            }
            return stayHours;
        }else{
            return "";
        }
    }
}
